﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using AMM.Business;
using AMM.Business.Config;
using AMM.CustomClassLibrary;
using AMM.CustomWinComponents.Validator;
using AMM.CustomWinControls;
using AMM.Model;
using AMM.Model.Config;

namespace AMM.Forms.Config {
    public partial class FrmRole : FrmRoleBase {

        private PowerHelper _powerHelper;
        private UserProcessor _userProcessor;
        private RoleProcessor _roleProcessor;
        private FunctionProcessor _funcProcessor;
        private List<RoleViewModel> _roleList;
        private List<UserViewModel> _userList;
        private List<UserViewModel> _ownUserList;
        private List<FunctionViewModel> _ownFuncList;
        private List<Function> _funcList;

        #region Override

        protected override string FunctionCode {
            get { return "AMM1102"; }
        }

        protected override void Button_Click(object sender, EventArgs e) {
            Button btn = sender as Button;
            switch (btn.Name) {
                case "btnAddUser":
                    this.dgvUsers.GetSelectedRows<UserViewModel>().ForEach(x => {
                        if (!this._ownUserList.Contains(x)) {
                            this._ownUserList.Add(x);
                        }
                    });
                    break;
                case "btnRemoveUser":
                    this.dgvOwnUsers.GetSelectedRows<UserViewModel>().ForEach(x => {
                        this._ownUserList.Remove(x);
                    });
                    break;
                case "btnAddFunc":
                    this.AddFunction();
                    break;
                case "btnRemoveFunc":
                    this.dgvOwnFunc.GetSelectedRows<FunctionViewModel>().ForEach(x => {
                        this._ownFuncList.Remove(x);
                    });
                    break;
                case "btnExpandAll":
                    this.tvFuncPowers.ExpandAll();
                    break;
                case "btnCollapse":
                    this.tvFuncPowers.CollapseAll();
                    break;
            }

            this.BindOwnFunc();
            this.BindOwnUsers();
        }

        protected override void Add() {
            this._ownUserList.Clear();
            this._ownFuncList.Clear();
            this.ResetForms();
            this.FBS.CurrentItem = new Role() { IsEnabled = true, ClassStatus = ClassStatus.Added };

            this.btnAddUser.Enabled = true;
            this.btnRemoveUser.Enabled = true;
            this.btnAddFunc.Enabled = true;
            this.btnRemoveFunc.Enabled = true;
            this.gbRole.Enabled = true;
            this.validator.ClearAllControlErrorIcons();
            base.Add();
        }

        protected override void Amend() {
            List<RoleViewModel> selectedList = this.dgvRoleList.GetSelectedRows<RoleViewModel>();
            if (selectedList.Count > 1) { this.OnlySelectSingleRecord(); return; }
            if (selectedList.Count == 0) { this.ShouldSelectSingleRecord(); return; }

            Role role = new Role();
            this.CreateNewThread(() => {
                role = this._roleProcessor.FetchRoleById(selectedList[0].Key);
                role.ClassStatus = ClassStatus.Updated;
                this._ownUserList = this._userProcessor.FetchUserViewModelList(role.RoleId);
                this._ownFuncList = this._funcProcessor.FetchFunctionViewModelList(role.RoleId);
            }, () => {
                this.FBS.CurrentItem = role;
                this.BindOwnUsers();
                this.BindOwnFunc();
                this.btnAddUser.Enabled = true;
                this.btnRemoveUser.Enabled = true;
                this.btnAddFunc.Enabled = true;
                this.btnRemoveFunc.Enabled = true;
                this.gbRole.Enabled = true;
                base.Amend();
            });
        }

        protected override void Save() {
            base.Save();
            this.CreateNewThread(() => {
                this.PreventCancel = true;
                Role role = this.FBS.CurrentItem;
                role.UserRoles.Clear();
                role.RoleFunctions.Clear();
                this.dgvOwnUsers.Rows
                    .Cast<DataGridViewRow>()
                    .Select(x => Convert.ToInt32(x.Cells["Key"].Value))
                    .ToList().ForEach(x => {
                        role.UserRoles.Add(new UserRole() {
                            RoleId = role.RoleId,
                            UserId = x
                        });
                    });
                this.dgvOwnFunc.Rows
                    .Cast<DataGridViewRow>()
                    .Select(x => {
                        return new {
                            FunctionId = Convert.ToInt32(x.Cells["Key"].Value),
                            CurrentPowers = Convert.ToInt32(x.Cells["CurrentPowers"].Value)
                        };
                    }).ToList().ForEach(x => {
                        role.RoleFunctions.Add(new RoleFunction() {
                            RoleId = role.RoleId,
                            FunctionId = x.FunctionId,
                            Powers = x.CurrentPowers
                        });
                    });

                if (role.ClassStatus == ClassStatus.Added) {
                    role.CreatedBy = LoginUserName;
                    this._roleProcessor.Insert(role);
                }
                else {
                    role.ModifiedBy = LoginUserName;
                    this._roleProcessor.Update(role);
                }

                this._roleList = this._roleProcessor.FetchRoleViewModelList();
                this._ownUserList.Clear();
                this._ownFuncList.Clear();
                this.MDIParent.SetStatusInformation("保存成功");
            }, () => {
                this.ResetForms();
                this.PreventCancel = false;
            });
        }

        protected override void Delete() {
            base.Delete();
            List<RoleViewModel> selectedList = this.dgvRoleList.GetSelectedRows<RoleViewModel>();
            if (selectedList.Count == 0) { this.ShouldSelectSingleRecord(); return; }
            if (selectedList.Any(x => x.IsSystem)) {
                this.ShowError("系统保留角色不能被删除");
                return;
            }
            this.CreateNewThread(() => {
                this.PreventCancel = true;
                this._roleProcessor.Delete(selectedList.Select(x => x.Key).ToArray());
                this._roleList = this._roleProcessor.FetchRoleViewModelList();
                this._ownUserList.Clear();
                this._ownFuncList.Clear();
                this.MDIParent.SetStatusInformation("删除成功");
            }, () => {
                this.ResetForms();
                this.PreventCancel = false;
            });
        }

        #endregion

        public FrmRole() {
            InitializeComponent();

            this.dgvRoleList.DataGridViewModelType = typeof(RoleViewModel);
            this.dgvOwnUsers.DataGridViewModelType = typeof(UserViewModel);
            this.dgvUsers.DataGridViewModelType = typeof(UserViewModel);
            this.dgvOwnFunc.DataGridViewModelType = typeof(FunctionViewModel);
        }

        #region Private methods

        private void ResetForms() {
            this.BindRoles();
            this.BindOwnUsers();
            this.BindOwnFunc();
            this.FBS.CurrentItem = null;
            this.btnAddUser.Enabled = false;
            this.btnRemoveUser.Enabled = false;
            this.btnAddFunc.Enabled = false;
            this.btnRemoveFunc.Enabled = false;
            this.gbRole.Enabled = false;
        }

        private void CreateFormBindings() {
            this.FBS.CreateBinding(this.tbName, x => x.Text, y => y.Name);
            this.FBS.CreateBinding(this.tbDescription, x => x.Text, y => y.Description);
            this.FBS.CreateBinding(this.cbIsEnabled, x => x.Checked, y => y.IsEnabled);
        }

        private void BindUsers() {
            this.dgvUsers.DataSource = new SortableBindingList<UserViewModel>(this._userList);
        }

        private void BindOwnUsers() {
            this.dgvOwnUsers.DataSource = new SortableBindingList<UserViewModel>(this._ownUserList);
        }

        private void BindFunc() {
            Action<int, TreeNode> act = null;
            act = (i, t) => {
                TreeNode tn;
                this._funcList.Where(x => x.ParentFunctionId == i).ToList().ForEach(x => {
                    tn = t.Nodes.Add(x.Code, x.Name);
                    if (x.DesignPowers > 0) {
                        this._powerHelper.FetchPowers(x.DesignPowers).ForEach(y => {
                            tn.Nodes.Add(new TreeNode() {
                                Text = this._powerHelper.GetPowerDescription(y),
                                Name = ((int)y).ToString()
                            });
                        });
                    }
                    act.Invoke(x.FunctionId, tn);
                });

            };

            Function funcRoot = this._funcList.Find(x => x.ParentFunctionId == 0);
            TreeNode nodeRoot = this.tvFuncPowers.Nodes.Add(funcRoot.Code, funcRoot.Name);
            act.Invoke(funcRoot.FunctionId, nodeRoot);
            nodeRoot.Expand();
        }

        private void BindOwnFunc() {
            this.dgvOwnFunc.DataSource = new SortableBindingList<FunctionViewModel>(this._ownFuncList);
        }

        private void BindRoles() {
            this.dgvRoleList.DataSource = new SortableBindingList<RoleViewModel>(this._roleList);
        }

        private void BindValidation() {
            this.validator.SetType(this.tbName, ValidationType.Required);
            this.validator.SetRequiredMessage(this.tbName, this.RequiredMessage);
        }

        private void NodeChecked(TreeNode tn) {
            if (tn.Nodes.Count > 0) {
                tn.Nodes.Cast<TreeNode>().ToList().ForEach(x => {
                    x.Checked = tn.Checked;
                    if (x.Nodes.Count > 0) {
                        this.NodeChecked(x);
                    }
                });
            }
        }

        private void AddFunction() {
            int powerValue;
            Dictionary<string, int> powerDict = new Dictionary<string, int>();
            Action<TreeNode> act = null;
            act = tn => {
                tn.Nodes.Cast<TreeNode>().ToList().ForEach(x => {
                    if (int.TryParse(x.Name, out powerValue) && x.Checked) {
                        if (!powerDict.ContainsKey(x.Parent.Name)) {
                            powerDict.Add(x.Parent.Name, powerValue);
                        }
                        else {
                            powerDict[x.Parent.Name] += powerValue;
                        }
                    }
                    act.Invoke(x);
                });
            };

            act.Invoke(this.tvFuncPowers.Nodes[0]);
            powerDict.ToList().ForEach(x => {
                FunctionViewModel fvm = this._funcProcessor.FetchFunctionByCode(x.Key);
                FunctionViewModel fvmExist = this._ownFuncList.FirstOrDefault(y => y.Code == x.Key);
                if (fvmExist == null) {
                    fvm.CurrentPowers = x.Value;
                    fvm.DesignPowers = this._powerHelper.GetPowerDescriptions(x.Value);
                    this._ownFuncList.Add(fvm);
                }
                else {
                    fvmExist.CurrentPowers = x.Value;
                    fvmExist.DesignPowers = this._powerHelper.GetPowerDescriptions(x.Value);
                }
            });
        }

        #endregion

        private void FrmRole_Load(object sender, EventArgs e) {
            this.CreateNewThread(() => {
                this.PreventCancel = true;
                this.FBS = new FlexBindingSource<Role>();

                this._powerHelper = new PowerHelper();
                this._userProcessor = new UserProcessor();
                this._roleProcessor = new RoleProcessor();
                this._funcProcessor = new FunctionProcessor();
                this._userList = this._userProcessor.FetchUserViewModelList();
                this._roleList = this._roleProcessor.FetchRoleViewModelList();
                this._funcList = this._funcProcessor.FetchFunctionList();
                this._ownUserList = new List<UserViewModel>();
                this._ownFuncList = new List<FunctionViewModel>();
            }, () => {
                this.WindowState = FormWindowState.Maximized;

                this.BindUsers();
                this.BindFunc();
                this.ResetForms();
                this.CreateFormBindings();
                this.BindValidation();
                this.PreventCancel = false;
            });

        }

        private void tvFuncPowers_AfterCheck(object sender, TreeViewEventArgs e) {
            this.NodeChecked(e.Node);
        }
    }
}
